package com.osfw.activiti.service.resource.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.osfw.activiti.domain.ProcessLinkInfo;
import com.osfw.activiti.domain.ProcessMetaInfo;
import com.osfw.activiti.domain.ProcessNodeInfo;
import com.osfw.activiti.entity.resource.ActReProcdef;
import com.osfw.activiti.enums.SuspensionState;
import com.osfw.activiti.enums.resource.ProcdefActionType;
import com.osfw.activiti.enums.resource.ProcdefNodeObj;
import com.osfw.activiti.enums.resource.ProcdefShareState;
import com.osfw.activiti.mapper.resource.ActReProcdefMapper;
import com.osfw.activiti.service.resource.IActReProcdefService;
import com.osfw.framework.enums.DeleteFlag;
import com.osfw.framework.exception.ServiceException;
import com.osfw.framework.utils.DateUtils;
import com.osfw.framework.utils.SnowflakeUtil;
import com.osfw.framework.utils.StringUtils;
import com.osfw.framework.utils.bean.BeanMapper;
import com.osfw.system.entity.manage.SysUser;
import com.osfw.system.service.manage.ISysDeptService;
import org.apache.commons.beanutils.ConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.osfw.activiti.enums.resource.ProcdefActionType.getActionType;

/**
 * 流程定义表 服务层实现
 */
@Service
public class ActReProcdefServiceImpl extends ServiceImpl<ActReProcdefMapper, ActReProcdef> implements IActReProcdefService {

    @Autowired
    private ISysDeptService sysDeptService;


    @Override
    public List<ActReProcdef> selectProcdefList(ActReProcdef procdef, SysUser sysUser) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getProcDefId, ActReProcdef::getProcKey, ActReProcdef::getProcName,
                ActReProcdef::getVersion, ActReProcdef::getDeployTime, ActReProcdef::getCategory, ActReProcdef::getDeptName,
                ActReProcdef::getShareState, ActReProcdef::getSuspensionState, ActReProcdef::getDeleteReason);
        queryWrapper.eq(StringUtils.isNotEmpty(procdef.getCategory()), ActReProcdef::getCategory, procdef.getCategory());
        queryWrapper.like(StringUtils.isNotEmpty(procdef.getProcKey()), ActReProcdef::getProcKey, procdef.getProcKey());
        queryWrapper.like(StringUtils.isNotEmpty(procdef.getProcName()), ActReProcdef::getProcName, procdef.getProcName());
        if (!sysUser.isAdmin()) {
            List<Long> deptIds = sysDeptService.selectNormalChildrenDeptIdById(sysUser.getDeptId());
            deptIds.add(sysUser.getDeptId());
            queryWrapper.and(wrapper -> {
                wrapper.in(ActReProcdef::getDeptId, deptIds)
                        .or()
                        .in(ActReProcdef::getShareState, Arrays.asList(ProcdefShareState.USE.getState(), ProcdefShareState.ALL.getState()));
            });
        }
        return list(queryWrapper);
    }

    @Override
    @Transactional
    public boolean saveProcdef(ActReProcdef procdef, SysUser sysUser) {
        if (procdef.getParams().get("action") != null) {
            Integer action = Integer.valueOf(procdef.getParams().get("action").toString());
            ProcdefActionType actionType = getActionType(action);
            switch (actionType) {
                case STAGING:
                    // 暂存时，设置del_flag=1（注：仅新增流程支持暂存）
                    if (procdef.getProcDefId() == null) {
                        // 暂存新增流程时
                        procdef.setDeptId(sysUser.getDeptId());
                        procdef.setDeptName(sysUser.getDeptName());
                        procdef.setSuspensionState(SuspensionState.STAGING.getState());
                        save(procdef);
                    } else if (procdef.getSuspensionState() == null) {
                        // 暂存流程修改时
                        updateById(procdef);
                    } else {
                        ServiceException.throw500("不支持暂存条件");
                    }
                    break;
                case RELEASE:
                    // 发布，查询最新版本并停用，标识历史版本停用理由为版本升级，指定当前版本号（仅初始数据或暂存状态可发布）
                    if (procdef.getProcDefId() != null) {
                        ActReProcdef released = getById(procdef.getProcDefId());
                        if (released != null) {
                            procdef = released;
                        }
                    }
                    LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.select(ActReProcdef::getProcDefId, ActReProcdef::getVersion);
                    if(procdef.getProcDefId() != null) {
                        queryWrapper.ne(ActReProcdef::getProcDefId, procdef.getProcDefId());
                    }
                    queryWrapper.eq(ActReProcdef::getProcKey, procdef.getProcKey());
                    queryWrapper.orderByDesc(ActReProcdef::getVersion);
                    List<ActReProcdef> List = list(queryWrapper);
                    if (List.isEmpty()) {
                        // 初始流程
                        procdef.setVersion(1);
                    } else {
                        // 迭代流程
                        ActReProcdef lastProcdef = List.stream().findFirst().get();
                        procdef.setVersion(lastProcdef.getVersion() == null ? 1 : lastProcdef.getVersion() + 1);
                        LambdaUpdateWrapper<ActReProcdef> historyWrapper = new LambdaUpdateWrapper<>();
                        historyWrapper.eq(ActReProcdef::getProcDefId, lastProcdef.getProcDefId());
                        historyWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.SUSPEND.getState());
                        historyWrapper.set(ActReProcdef::getDeleteReason, "流程版本升级，升级版本号为：" + procdef.getVersion());
                        historyWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                        historyWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                        historyWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                        update(historyWrapper);
                    }
                    if (procdef.getProcDefId() == null) {
                        procdef.setProcDefId(SnowflakeUtil.generatorId());
                    }
                    procdef.setDeployTime(new Date());
                    procdef.setSuspensionState(SuspensionState.RELEASE.getState());
                    procdef.setDelFlag(DeleteFlag.OK.getCode());
                    procdef.setDeleteReason(null);
                    saveOrUpdate(procdef);
                    break;
                case FALLBACK:
                    // 回退，指定版本激活，其他版本停用，并标识历史激活版本停用得自定义理由为回退指定版本（注：仅激活状态可回退历史版本）
                    ActReProcdef fallbacked = getById(procdef.getProcDefId());
                    LambdaUpdateWrapper<ActReProcdef> fallbackWrapper = new LambdaUpdateWrapper<>();
                    fallbackWrapper.eq(ActReProcdef::getProcKey, fallbacked.getProcKey());
                    fallbackWrapper.eq(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
                    fallbackWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.SUSPEND.getState());
                    fallbackWrapper.set(ActReProcdef::getDeleteReason, procdef.getDeleteReason());
                    fallbackWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    fallbackWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    fallbackWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(fallbackWrapper);
                    fallbackWrapper.clear();
                    fallbackWrapper.eq(ActReProcdef::getProcKey, fallbacked.getProcKey());
                    fallbackWrapper.eq(ActReProcdef::getVersion, procdef.getVersion());
                    fallbackWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
                    fallbackWrapper.set(ActReProcdef::getDeleteReason, null);
                    fallbackWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    fallbackWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    fallbackWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(fallbackWrapper);
                    break;
                case ACTIVATION:
                    // 激活，当前版本激活，其他版本停用，并标识历史激活版本停用理由为激活指定版本（注：仅停用状态可激活）
                    ActReProcdef activated = getById(procdef.getProcDefId());
                    LambdaUpdateWrapper<ActReProcdef> activateWrapper = new LambdaUpdateWrapper<>();
                    activateWrapper.eq(ActReProcdef::getProcKey, activated.getProcKey());
                    activateWrapper.eq(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
                    activateWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.SUSPEND.getState());
                    activateWrapper.set(ActReProcdef::getDeleteReason, "流程版本激活，激活版本号为：" + activated.getVersion() + "，停用当前版本。");
                    activateWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    activateWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    activateWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(activateWrapper);
                    activateWrapper.clear();
                    activateWrapper.eq(ActReProcdef::getProcDefId, activated.getProcDefId());
                    activateWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
                    activateWrapper.set(ActReProcdef::getDeleteReason, null);
                    activateWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    activateWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    activateWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(activateWrapper);
                    break;
                case SUSPEND:
                    // 挂起，当前版本挂起，并标识停用自定义理由（注：仅激活状态可挂起）
                    LambdaUpdateWrapper<ActReProcdef> suspendWrapper = new LambdaUpdateWrapper<>();
                    Long[] suspendIdArr = (Long[]) ConvertUtils.convert(procdef.getParams().get("ids").toString().split(","), Long.class);
                    suspendWrapper.in(ActReProcdef::getProcDefId, Arrays.asList(suspendIdArr));
                    suspendWrapper.set(ActReProcdef::getSuspensionState, SuspensionState.SUSPEND.getState());
                    suspendWrapper.set(ActReProcdef::getDeleteReason, procdef.getDeleteReason());
                    suspendWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    suspendWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    suspendWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(suspendWrapper);
                    break;
                case SHARE:
                    // 分享（注：仅激活状态可分享）
                    LambdaQueryWrapper<ActReProcdef> shareQuery = new LambdaQueryWrapper<>();
                    Long[] shareIdArr = (Long[]) ConvertUtils.convert(procdef.getParams().get("ids").toString().split(","), Long.class);
                    shareQuery.select(ActReProcdef::getProcKey);
                    shareQuery.in(ActReProcdef::getProcDefId, Arrays.asList(shareIdArr));
                    List<ActReProcdef> shareList = list(shareQuery);
                    if(!shareList.isEmpty()){
                        LambdaUpdateWrapper<ActReProcdef> shareWrapper = new LambdaUpdateWrapper<>();
                        shareWrapper.in(ActReProcdef::getProcKey, shareList.stream().map(x -> x.getProcKey()).collect(Collectors.toList()));
                        shareWrapper.set(ActReProcdef::getShareState, procdef.getShareState());
                        shareWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                        shareWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                        shareWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                        update(shareWrapper);
                    }
                    break;
                case CANCEL_SHARE:
                    // 取消分享
                    LambdaQueryWrapper<ActReProcdef> cancelShareQuery = new LambdaQueryWrapper<>();
                    Long[] cancelShareIdArr = (Long[]) ConvertUtils.convert(procdef.getParams().get("ids").toString().split(","), Long.class);
                    cancelShareQuery.select(ActReProcdef::getProcKey);
                    cancelShareQuery.in(ActReProcdef::getProcDefId, Arrays.asList(cancelShareIdArr));
                    List<ActReProcdef> cancelShareList = list(cancelShareQuery);
                    if(!cancelShareList.isEmpty()) {
                        LambdaUpdateWrapper<ActReProcdef> cancelShareWrapper = new LambdaUpdateWrapper<>();
                        cancelShareWrapper.in(ActReProcdef::getProcKey, cancelShareList.stream().map(x -> x.getProcKey()).collect(Collectors.toList()));
                        cancelShareWrapper.set(ActReProcdef::getShareState, ProcdefShareState.DEPT.getState());
                        cancelShareWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                        cancelShareWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                        cancelShareWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                        update(cancelShareWrapper);
                    }
                    break;
                case DELETE:
                    // 删除，删除当前版本，并标识删除自定义理由
                    LambdaUpdateWrapper<ActReProcdef> deleteWrapper = new LambdaUpdateWrapper<>();
                    Long[] deleteIdArr = (Long[]) ConvertUtils.convert(procdef.getParams().get("ids").toString().split(","), Long.class);
                    deleteWrapper.in(ActReProcdef::getProcDefId, Arrays.asList(deleteIdArr));
                    deleteWrapper.set(ActReProcdef::getDelFlag, DeleteFlag.DELETED.getCode());
                    deleteWrapper.set(ActReProcdef::getDeleteReason, procdef.getDeleteReason());
                    deleteWrapper.set(ActReProcdef::getUpdateBy, sysUser.getUserId());
                    deleteWrapper.set(ActReProcdef::getUpdateByName, sysUser.getUserName());
                    deleteWrapper.set(ActReProcdef::getUpdateTime, DateUtils.getNowDate());
                    update(deleteWrapper);
                    break;
            }

        } else {
            ServiceException.throw500("操作类型[action]不能为空");
        }
        return true;
    }

    @Override
    public List<ActReProcdef> selectProcdefByProcKey(String prockey) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getProcDefId, ActReProcdef::getProcKey, ActReProcdef::getProcName, ActReProcdef::getVersion,
                ActReProcdef::getShareState, ActReProcdef::getSuspensionState, ActReProcdef::getDelFlag);
        queryWrapper.eq(ActReProcdef::getProcKey, prockey);
        queryWrapper.orderByDesc(ActReProcdef::getVersion);
        return list(queryWrapper);
    }

    @Override
    public ActReProcdef getLatestVersionProcdefByProcKey(String prockey) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActReProcdef::getProcKey, prockey);
        queryWrapper.eq(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
        queryWrapper.orderByDesc(ActReProcdef::getVersion);
        List<ActReProcdef> list = list(queryWrapper);
        return list.isEmpty() ? null : list.get(0);
    }

    @Override
    public List<ActReProcdef> selectLatestVersionProcdef(SysUser sysUser) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getProcDefId, ActReProcdef::getProcKey, ActReProcdef::getProcName, ActReProcdef::getVersion);
        queryWrapper.eq(ActReProcdef::getSuspensionState, SuspensionState.RELEASE.getState());
        if (!sysUser.isAdmin()) {
            List<Long> deptIds = sysDeptService.selectNormalChildrenDeptIdById(sysUser.getDeptId());
            deptIds.add(sysUser.getDeptId());
            queryWrapper.and(wrapper -> {
                wrapper.in(ActReProcdef::getDeptId, deptIds)
                        .or()
                        .in(ActReProcdef::getShareState, Arrays.asList(ProcdefShareState.USE.getState(), ProcdefShareState.ALL.getState()));
            });
        }
        queryWrapper.orderByDesc(ActReProcdef::getCreateTime, ActReProcdef::getVersion);
        List<ActReProcdef> list = list(queryWrapper);
        list = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ActReProcdef::getProcKey))), ArrayList::new));
        return list;
    }

    @Override
    public ProcessNodeInfo getStartNodeInfo(Long procDefId) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getMetaInfo);
        queryWrapper.eq(ActReProcdef::getProcDefId, procDefId);
        ActReProcdef procdef = getById(procDefId);
        return getStartNodeInfo(procdef);
    }

    @Override
    public ProcessNodeInfo getStartNodeInfo(ActReProcdef procdef) {
        if (procdef != null) {
            ProcessMetaInfo metaInfo = null;
            try {
                metaInfo = JSONObject.parseObject(procdef.getMetaInfo(), ProcessMetaInfo.class);
            } catch (Exception e) {
                ServiceException.throw500("流程解析异常", e.getMessage());
            }
            if (metaInfo != null) {
                List<ProcessNodeInfo> nodeInfos = metaInfo.getNodeDataArray();
                Optional<ProcessNodeInfo> optional = nodeInfos.stream().map(x -> BeanMapper.map(x, ProcessNodeInfo.class)).filter(x -> "Start".equals(x.getCategory())).findFirst();
                if (optional.isPresent()) {
                    return optional.get();
                } else {
                    ServiceException.throw500("流程配置信息不完善，未匹配到Start节点信息");
                }
            } else {
                ServiceException.throw500("流程配置信息不完善");
            }
        } else {
            ServiceException.throw500("未匹配到流程配置信息");
        }
        return null;
    }

    @Override
    public ProcessNodeInfo getNextNodeInfo(Long procDefId, String actKey) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getMetaInfo);
        queryWrapper.eq(ActReProcdef::getProcDefId, procDefId);
        ActReProcdef byId = getById(procDefId);
        if (byId != null) {
            ProcessMetaInfo metaInfo = null;
            try {
                metaInfo = JSONObject.parseObject(byId.getMetaInfo(), ProcessMetaInfo.class);
            } catch (Exception e) {
                ServiceException.throw500("流程解析异常", e.getMessage());
            }
            if (metaInfo != null) {
                List<ProcessNodeInfo> nodeInfos = metaInfo.getNodeDataArray();
                List<ProcessLinkInfo> linkInfos = metaInfo.getLinkDataArray();
                Optional<String> optional = linkInfos.stream().map(x -> BeanMapper.map(x, ProcessLinkInfo.class)).filter(x -> actKey.equals(x.getFrom())).map(x -> x.getTo()).findFirst();
                if (optional.isPresent()) {
                    String nextActKey = optional.get();
                    Optional<ProcessNodeInfo> nextOptional = nodeInfos.stream().filter(x -> x.getKey().equals(nextActKey)).findFirst();
                    if (nextOptional.isPresent()) {
                        ProcessNodeInfo nextNodeInfo = nextOptional.get();
                        return nextNodeInfo;
                    } else {
                        ServiceException.throw500("流程配置信息不完善，未匹配到下个节点信息");
                    }
                } else {
                    ServiceException.throw500("已是最后一个节点");
                }
            } else {
                ServiceException.throw500("流程配置信息不完善");
            }
        } else {
            ServiceException.throw500("未匹配到流程配置信息");
        }
        return null;
    }

    @Override
    public ProcessNodeInfo getNextNodeInfo(ActReProcdef procdef, String actKey) {
        if (procdef != null) {
            ProcessMetaInfo metaInfo = null;
            try {
                metaInfo = JSONObject.parseObject(procdef.getMetaInfo(), ProcessMetaInfo.class);
            } catch (Exception e) {
                ServiceException.throw500("流程解析异常", e.getMessage());
            }
            if (metaInfo != null) {
                List<ProcessNodeInfo> nodeInfos = metaInfo.getNodeDataArray();
                List<ProcessLinkInfo> linkInfos = metaInfo.getLinkDataArray();
                Optional<String> optional = linkInfos.stream().map(x -> BeanMapper.map(x, ProcessLinkInfo.class)).filter(x -> actKey.equals(x.getFrom())).map(x -> x.getTo()).findFirst();
                if (optional.isPresent()) {
                    String nextActKey = optional.get();
                    Optional<ProcessNodeInfo> nextOptional = nodeInfos.stream().filter(x -> x.getKey().equals(nextActKey)).findFirst();
                    if (nextOptional.isPresent()) {
                        ProcessNodeInfo nextNodeInfo = nextOptional.get();
                        // 获取下个流程节点人员
                        List<SysUser> nextUsers = getNextNodeAssignees(nextNodeInfo);
                        nextNodeInfo.setAssignees(nextUsers);
                        return nextNodeInfo;
                    } else {
                        ServiceException.throw500("流程配置信息不完善，未匹配到下个节点信息");
                    }
                } else {
                    ServiceException.throw500("已是最后一个节点");
                }
            } else {
                ServiceException.throw500("流程配置信息不完善");
            }
        } else {
            ServiceException.throw500("未匹配到流程配置信息");
        }
        return null;
    }

    @Override
    public List<SysUser> getNextNodeAssignees(ProcessNodeInfo procNextNode) {
        List<SysUser> assignees = new ArrayList<>();
        if (procNextNode != null && procNextNode.getChoice() != null && !procNextNode.getChoice().isEmpty()) {
            procNextNode.getChoice().stream().map(choice -> {
                if (ProcdefNodeObj.DEPARTMENT.getCode().equals(procNextNode.getObj())) {
                    return Long.getLong(choice.get("deptId").toString());
                } else {
                    return Long.getLong(choice.get("userId").toString());
                }
            }).collect(Collectors.toList());
            if (ProcdefNodeObj.DEPARTMENT.getCode().equals(procNextNode.getObj())) {
                List<Long> deptIds = procNextNode.getChoice().stream().map(choice -> Long.getLong(choice.get("deptId").toString())).collect(Collectors.toList());
                assignees = sysDeptService.selectDeptUserByProc(deptIds, procNextNode.getIsByDirectLeader());
            } else {
                assignees = procNextNode.getChoice().stream().map(choice ->
                        new SysUser()
                                .setUserId(Long.getLong(choice.get("userId").toString()))
                                .setUserName(choice.get("userName").toString())
                                .setDeptId(Long.getLong(choice.get("deptId").toString()))
                                .setDeptName(choice.get("deptName").toString())
                ).collect(Collectors.toList());
            }
        } else {
            ServiceException.throw500("流程节点信息不全，未配置节点签收人！");
        }
        return assignees;
    }

    @Override
    public ProcessNodeInfo getEndNodeInfo(Long procDefId) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getMetaInfo);
        queryWrapper.eq(ActReProcdef::getProcDefId, procDefId);
        ActReProcdef byId = getById(procDefId);
        if (byId != null) {
            ProcessMetaInfo metaInfo = null;
            try {
                metaInfo = JSONObject.parseObject(byId.getMetaInfo(), ProcessMetaInfo.class);
            } catch (Exception e) {
                ServiceException.throw500("流程解析异常", e.getMessage());
            }
            if (metaInfo != null) {
                List<ProcessNodeInfo> nodeInfos = metaInfo.getNodeDataArray();
                Optional<ProcessNodeInfo> optional = nodeInfos.stream().map(x -> BeanMapper.map(x, ProcessNodeInfo.class)).filter(x -> "End".equals(x.getCategory())).findFirst();
                if (optional.isPresent()) {
                    return optional.get();
                } else {
                    ServiceException.throw500("流程配置信息不完善，未匹配到End节点信息");
                }
            } else {
                ServiceException.throw500("流程配置信息不完善");
            }
        } else {
            ServiceException.throw500("未匹配到流程配置信息");
        }
        return null;
    }

    @Override
    public boolean isEndNode(Long procDefId, String actKey) {
        LambdaQueryWrapper<ActReProcdef> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ActReProcdef::getMetaInfo);
        queryWrapper.eq(ActReProcdef::getProcDefId, procDefId);
        ActReProcdef byId = getById(procDefId);
        if (byId != null) {
            ProcessMetaInfo metaInfo = null;
            try {
                metaInfo = JSONObject.parseObject(byId.getMetaInfo(), ProcessMetaInfo.class);
            } catch (Exception e) {
                ServiceException.throw500("流程解析异常", e.getMessage());
            }
            if (metaInfo != null) {
                List<ProcessNodeInfo> nodeInfos = metaInfo.getNodeDataArray();
                long count = nodeInfos.stream().map(x -> BeanMapper.map(x, ProcessNodeInfo.class)).filter(x -> actKey.equals(x.getKey()) && "End".equals(x.getCategory())).count();
                return count > 0 ? true : false;
            } else {
                ServiceException.throw500("流程配置信息不完善");
            }
        } else {
            ServiceException.throw500("未匹配到流程配置信息");
        }
        return false;
    }

}
